from rest_framework.viewsets import ModelViewSet
from cron.models import CronJob,DjangoCronjob
from cron.serializers import CronJobSerializer,DjangoCronjobSerializer
from rest_framework.response import Response
from django.conf import settings
from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.views import APIView
from cmdb.models import Server
from system_config.models import Credential
import os
try:
    from libs.ansible_cicd import AnsibleApi
except Exception as e:
    print("导入Ansible模块错误！")
#django_apscheduler 定时任务
from django_apscheduler.models import DjangoJob,DjangoJobExecution
from .serializers import DjangoJobExecutionSerializer
from cron.apps import scheduler  #使用apps.py里面的调度器实例


class CronJobViewSet(ModelViewSet):
    queryset = CronJob.objects.all()
    serializer_class = CronJobSerializer

    filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend]  # 指定过滤器
    search_fields = ('name',)  # 指定可搜索的字段

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        try:
            serializer.is_valid(raise_exception=True)
            self.perform_create(serializer)
            res = {'code': 200, 'msg': '创建成功'}
        except Exception as e:
            res = {'code': 400, 'msg': '%s' %e}
        return Response(res)

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        res = {'code': 200, 'msg': '更新成功'}
        return Response(res)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        res = {'code': 200, 'msg': '删除成功'}
        return Response(res)


class EnableView(APIView):
    def put(self, request):
        print(request.data)

        status = request.data.get('status')
        corn_id = int(request.data.get('id'))
        server_ids = request.data.get('server_ids')
        cron_script = request.data.get('cron_script')
        name = request.data.get('name')
        command = request.data.get('command')
        schedule_str = str(request.data.get('schedule'))
        schedule_list = schedule_str.split(' ')
        minute = schedule_list[0]
        hour = schedule_list[1]
        day = schedule_list[2]
        month = schedule_list[3]
        weekday = schedule_list[4]
        print(minute)

        # 将脚本写入文件
        command_file = '/tmp/' + command
        with open(command_file, 'w') as f:
            f.write(cron_script)

        ansible = AnsibleApi()
        # 将发布配置部分变量传递给playbook使用
        extra_vars = {
            "name": name,
            "command_file": command_file,
            "minute": minute,
            "hour": hour,
            "day": day,
            "month": month,
            "weekday": weekday,
        }
        ansible.variable_manager._extra_vars = extra_vars

        # 创建一个分组
        ansible.inventory.add_group("webservers")
        for i in server_ids:
            server_obj = Server.objects.get(id=i)
            # ssh_ip、ssh_port、ssh用户名、ssh密码
            ssh_ip = server_obj.ssh_ip
            ssh_port = server_obj.ssh_port
            if server_obj.credential:
                ssh_user = server_obj.credential.username
                if server_obj.credential.auth_mode == 1:
                    ssh_pass = server_obj.credential.password
                    ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_pass', value=ssh_pass)
                else:
                    ssh_key = server_obj.credential.private_key
                    key_file = "/tmp/.ssh_key"
                    with open(key_file, 'w') as f:
                        f.write(ssh_key)
                    ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_private_key_file', value=key_file)
            else:
                ssh_user = 'root'
            ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_port', value=ssh_port)
            ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_user', value=ssh_user)
            # 向组内添加主机
            ansible.inventory.add_host(host=ssh_ip,group="webservers")
        if status == 2:
            if command_file.endswith('.sh'):
                playbook = os.path.join(settings.BASE_DIR, 'cron/files/addcron_sh.yaml')
            else:
                playbook = os.path.join(settings.BASE_DIR, 'cron/files/addcron_py.yaml')
            run_status = ansible.playbook_run([playbook])  # 返回一个状态码，0是正常，非0是有任务异常
            result = ansible.get_result()
            if run_status == 0:
                CronJob.objects.filter(id=corn_id).update(status=2)
                res = {'code': 200, 'msg': '启用成功'}
            else:
                CronJob.objects.filter(id=corn_id).update(status=1)
                res = {'code': 500, 'msg': '启用失败！', 'data': result}
        else:
            if command_file.endswith('.sh'):
                playbook = os.path.join(settings.BASE_DIR, 'cron/files/removecron_sh.yaml')
            else:
                playbook = os.path.join(settings.BASE_DIR, 'cron/files/removecron_py.yaml')
            run_status = ansible.playbook_run([playbook])  # 返回一个状态码，0是正常，非0是有任务异常
            result = ansible.get_result()
            if run_status == 0:
                CronJob.objects.filter(id=corn_id).update(status=1)
                res = {'code': 200, 'msg': '禁用成功'}
            else:
                CronJob.objects.filter(id=corn_id).update(status=2)
                res = {'code': 500, 'msg': '禁用失败！', 'data': result}
        return Response(res)



class DjangoCronjobViewSet(ModelViewSet):
    queryset = DjangoCronjob.objects.all()
    serializer_class = DjangoCronjobSerializer

    filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend]  # 指定过滤器
    # search_fields = ('command',)  # 指定可搜索的字段
    # 指定自定义的过滤器
    from .serializers import DjangoCronjobFilter
    filterset_class = DjangoCronjobFilter

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        try:
            serializer.is_valid(raise_exception=True)
            # self.perform_create(serializer)
            server_ids = request.data.get('server_ids')
            #脚本内容
            cron_script = request.data.get('cron_script')
            #脚本名
            command = request.data.get('command')
            note = request.data.get('note')
            schedule_str = str(request.data.get('schedule'))
            schedule_list = schedule_str.split(' ')
            minute = schedule_list[0]
            hour = schedule_list[1]
            day = schedule_list[2]
            month = schedule_list[3]
            weekday = schedule_list[4]
            name = request.data.get('name')
            try:
                scheduler.add_job(execute, 'cron', minute=minute,hour=hour,day=day,month=month,week=weekday,id=name,args=[command,cron_script,server_ids],replace_existing=True)
                # 如果没有运行再启动调度器，如果调度器之前没有被启动过，那么它将会开始执行所有已经添加并且没有被暂停的任务。
                if not scheduler.running:
                    scheduler.start()
                #添加任务后暂停运行，后面手动开启
                job = scheduler.get_job(name)
                if job:
                    job.pause()
            except Exception as e:
                res = {'code': 500, 'msg': '%s' % e}
                return Response(res)
            job = DjangoJob.objects.get(id=name)
            DjangoCronjob.objects.create(
                job=job,
                server_ids=server_ids,
                cron_script=cron_script,
                command=command,
                schedule=schedule_str,
                note=note,
            )
            res = {'code': 200, 'msg': '创建成功'}
        except Exception as e:
            res = {'code': 400, 'msg': '%s' %e}
        return Response(res)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        try:
            DjangoJobExecution.objects.filter(job_id=str(instance)).delete()  #删除执行记录
            self.perform_destroy(instance)  #删除数据
            scheduler.remove_job(str(instance)) #移除任务
            res = {'code': 200, 'msg': '删除成功'}
        except Exception as e:
            res = {'code': 500, 'msg': '%s' %e}
        return Response(res)


#定时任务执行函数
def execute(command,cron_script,server_ids):
    # 将脚本写入文件
    command_file = '/tmp/' + command
    with open(command_file, 'w') as f:
        f.write(cron_script)

    ansible = AnsibleApi()
    # 将发布配置部分变量传递给playbook使用
    extra_vars = {
        "command_file": command_file,
    }
    ansible.variable_manager._extra_vars = extra_vars

    # 创建一个分组
    ansible.inventory.add_group("webservers")
    for i in server_ids:
        server_obj = Server.objects.get(id=i)
        # ssh_ip、ssh_port、ssh用户名、ssh密码
        ssh_ip = server_obj.ssh_ip
        ssh_port = server_obj.ssh_port
        if server_obj.credential:
            ssh_user = server_obj.credential.username
            if server_obj.credential.auth_mode == 1:
                ssh_pass = server_obj.credential.password
                ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_pass', value=ssh_pass)
            else:
                ssh_key = server_obj.credential.private_key
                key_file = "/tmp/.ssh_key"
                with open(key_file, 'w') as f:
                    f.write(ssh_key)
                ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_private_key_file',
                                                           value=key_file)
        else:
            ssh_user = 'root'
        ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_port', value=ssh_port)
        ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_user', value=ssh_user)
        # 向组内添加主机
        ansible.inventory.add_host(host=ssh_ip, group="webservers")
    if command_file.endswith('.sh'):
        playbook = os.path.join(settings.BASE_DIR, 'cron/files/cron_sh.yaml')
    else:
        playbook = os.path.join(settings.BASE_DIR, 'cron/files/cron_py.yaml')
    status = ansible.playbook_run([playbook])  # 返回一个状态码，0是正常，非0是有任务异常
    result = ansible.get_result()

#定时任务启动停止
class DjangoCronjobView(APIView):
    def post(self,request):
        print(request.data)
        name = request.data.get('job')['id']
        command = request.data.get('command')
        status = request.data.get('status')
        job = scheduler.get_job(name)
        if status == 2:
            try:
                #恢复任务
                if job:
                    job.resume()
                    DjangoCronjob.objects.filter(command=command).update(status=2)
                res = {'code': 200, 'msg': '启动成功'}
                return Response(res)
            except Exception as e:
                res = {'code': 500, 'msg': '%s' %e}
                return Response(res)
        else:
            try:
                # 暂停任务
                print(job)
                if job:
                    job.pause()
                    DjangoCronjob.objects.filter(command=command).update(status=1)
                res = {'code': 200, 'msg': '关闭成功'}
                return Response(res)
            except Exception as e:
                res = {'code': 500, 'msg': '%s' % e}
                return Response(res)


#定时任务执行记录
class DjangoJobExecutionViewSet(ModelViewSet):
    queryset = DjangoJobExecution.objects.all()
    serializer_class = DjangoJobExecutionSerializer

    filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend]  # 指定过滤器
    # search_fields = ('name',)  # 指定可搜索的字段
    # 指定自定义的过滤器
    from .serializers import DjangoJobExecutionFilter
    filterset_class = DjangoJobExecutionFilter

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        res = {'code': 200, 'msg': '删除成功'}
        return Response(res)



#批量删除任务日志
class DeletRecordView(APIView):
    def post(self,request):
        # print(request.data.get('selectrow'))
        #前端传递过来的所选择的id
        ids = request.data.get('selectrow')
        try:
            for i in ids:
                id = i['id']
                DjangoJobExecution.objects.get(id=id).delete()
            res = {'code': 200, 'msg': '删除成功'}
            return Response(res)
        except Exception as e:
            res = {'code': 500, 'msg': '%s' %e}
            return Response(res)
